#ifndef CLIENT_CLIENT_H
#define CLIENT_CLIENT_H
//******************************************************************************
//this code is protected by the GNU affero GPLv3
//author:Sylvain BERTRAND <sylvain.bertrand AT gmail dot com>
//                        <digital.ragnarok AT gmail dot com>
//******************************************************************************
#define MSG_FDS_MAX 8
#define MSG_BUF_SZ PAGE_SZ//get a single cpu page
struct msg{
  struct msg_hdr hdr;
  u8 buf[MSG_BUF_SZ];
  s32 dws;
  u8 cm_buf[MSG_FDS_MAX*CMSG_SPACE(sizeof(i))];

  u8 fd;//current index of the first not consumed file descriptor
  i fds[MSG_FDS_MAX];//hold decoded control message fds

  u32 *req;//current request
  s16 req_dws;
  u16 req_op;
};
#define CLIENT_OBJS_MAX 1024
#define CLIENT_OBJ_TYPE_MASK         0x000003ff
#define   CLIENT_OBJ_INVALID         0x00000001
#define   CLIENT_OBJ_REGISTRY_MAP    0x00000002
#define   CLIENT_OBJ_SHM_POOL        0x00000004
#define   CLIENT_OBJ_BUFFER          0x00000008//virtual
#define   CLIENT_OBJ_SHM_POOL_BUFFER 0x00000010//inherits buffer
#define   CLIENT_OBJ_SURFACE         0x00000020
#define   CLIENT_OBJ_REGION          0x00000040
#define   CLIENT_OBJ_SHELL_SURFACE   0x00000080
#define   CLIENT_OBJ_POINTER         0x00000100
#define   CLIENT_OBJ_KEYBOARD        0x00000200
#define CLIENT_OBJ_VISIBLE           0x80000000//visible over the wire, id valid
struct client_obj{
  s32 n;//reference count for object lifetime
  void (*release)(struct client *,s32);//called when ref count drops to zero

  u32 state;//wire visible or not, type which defines the valid union member
  u32 id;
  union{
    struct registry_map map;
    struct shm_pool pool;
    struct shm_pool_buffer buffer;
    struct surface surface;
    struct region region;
    struct shell_surface shell_surface;
    struct pointer pointer;
    struct keyboard keyboard;
  };
};

#define CLIENT_FIRST_VALID_ID 1
struct client{
  i so;
  struct client_obj objs[CLIENT_OBJS_MAX];
};

#define CLIENTS_MAX 128
#ifdef CLIENT_C
struct client clients[CLIENTS_MAX];
#else
extern struct client clients[CLIENTS_MAX];
#endif

void client_obj_ref(struct client *c,s32 o);
s32 client_obj_unref(struct client *c,s32 o);
void client_obj_generic_release(struct client *c,s32 o);
s8 client_new(i so);
void client_kill(struct client *c);
s8 client_rd(struct client *c);
void clients_init(i srv_ep_fd);
void client_registry_publish(struct client *c, s32 name);
void client_registry_unpublish(struct client *c, s32 name);
#endif
